package xgb

import(
	"net"
)






/*
.type PipT:
*/
type PipT struct{
	data []byte
	con net.Conn
	idLst []uint32
	idBase uint32
	rqstSqc uint16
	rtSqc uint16
	rplQue [RPL_QUE_MOD]*RplQueT
	errQue [ERR_QUE_MOD]**ErrT
	EvtQue chan *EvtQueT
}





/*
..func Init:
*/
func Init()(pip *PipT){
	authName:=append([]byte("MIT-MAGIC-COOKIE-1"), 0, 0)
	authKey:=getAuthKey()
	keyLen:=byte(len(authKey))
	if padLen:=(4-len(authKey)%4)%4;padLen!=0{
		keyPad:=make([]byte, padLen)
		authKey=append(authKey, keyPad...)
	}
	initSend:=[]byte{0x42,//MSB first
									0,//unused
									0, 11,//protocol-major-version
									0, 0,//protocol-minor-version
									0, 18,//length of authorization-protocol-name
									0, keyLen,//length of authorization-protocol-data
									0, 0,//unused
								}

	initSend=append(initSend, authName...)//authorization-protocol-name&pad
	initSend=append(initSend, authKey...)//authorization-protocol-data&pad

	con,err:=net.Dial("unix", "/tmp/.X11-unix/X0"); if err!=nil{panic(err)}
	_,err=con.Write(initSend); if err!=nil{panic(err)}

	baseRet:=make([]byte,8)
	_,err=con.Read(baseRet); if err!=nil{panic(err)}

	allLen:=4*(uint32(BytesToUint16(baseRet[6:])))+8
	allRet:=make([]byte, allLen)
	copy(allRet, baseRet)
	con.Read(allRet[8:])
	if allRet[0]!=1{panic(string(allRet[8:]))}
	
	pip=&PipT{
		data: allRet,
		con: con,
		idLst: []uint32{},
		idBase: BytesToUint32(allRet[12:16]),
		EvtQue: make(chan *EvtQueT, EVT_QUE_LEN),//通道一定要在使用前初始化
	}
	go pip.dispatch()
	return
}





/*
..method Uninit:
*/
func(pip *PipT)Uninit(){
	err:=pip.con.Close(); if err!=nil{panic(err)}
}//Uninit




/*
..method Version():
*/
// 返回X Server提供的X System Protocol协议版本号，如"11.0"，其中"11"是主版本号，"0"是副版本号
func(pip *PipT)Version()[]uint16{
	return []uint16{BytesToUint16(pip.data[2:4]), BytesToUint16(pip.data[4:6])}
}//Version





/*
..method Vendor():
*/
func(pip *PipT)Vendor()(vend *VendorT){
	vendLen:=BytesToUint16(pip.data[24:26])
	vend=&VendorT{
		Name: string(pip.data[40:40+vendLen]),
		RlsNum: BytesToUint32(pip.data[8:12]),
	}
	return
}//Vendor
type VendorT struct{
	Name string
	RlsNum uint32
}//VendorT





/*
..method GenerateId:
*/
func(pip *PipT)GenerateId()(idRet uint32){
	if len(pip.idLst)==0{
		for i:=0;i<50;i++{
			pip.idLst=append(pip.idLst, pip.idBase)
			pip.idBase++
		}//for
	}//if
	idRet=pip.idLst[len(pip.idLst)-1]
	pip.idLst=pip.idLst[:len(pip.idLst)-1]
	return
}//GenerateId




/*
..method Screen:
*/
func(pip *PipT)Screen()*ScreenT{
	v:=BytesToUint16(pip.data[24:26])
	p:=(4-v%4)%4
	n:=uint16(pip.data[29])
	idx:=40+v+p+8*n

	return &ScreenT{
		Root: BytesToUint32(pip.data[idx:idx+4]),
		Depth: pip.data[idx+38],
		Visual: BytesToUint32(pip.data[idx+32:idx+36]),
		White: BytesToUint32(pip.data[idx+8:idx+12]),
		Black: BytesToUint32(pip.data[idx+12:idx+16]),
		PixWidth: BytesToUint16(pip.data[idx+20:idx+22]),
		PixHeight: BytesToUint16(pip.data[idx+22:idx+24]),
		MilWidth: BytesToUint16(pip.data[idx+24:idx+26]),
		MilHeight: BytesToUint16(pip.data[idx+26:idx+28]),
		BackStore: BackStoreT(pip.data[idx+36]),
		SaveUnder: pip.data[idx+37]!=0,
	}//ScreenT
}//Screen







/*
.type IdT:
*/
type IdT struct{
	val uint32
	next *IdT
}//IdT




/*
.type ScreenT:
*/
type ScreenT struct{
	Root uint32
	Depth uint8
	Visual uint32
	White uint32
	Black uint32
	PixWidth uint16
	PixHeight uint16
	MilWidth uint16
	MilHeight uint16
	BackStore BackStoreT
	SaveUnder bool
}//ScreenT